package cn.zcltd.btg.validjsonq;

import cn.zcltd.btg.validjsonq.cache.ValidJsonQCache;
import cn.zcltd.btg.validjsonq.exception.ValidJsonQException;
import cn.zcltd.btg.validq.DefaultValidateCallback;
import cn.zcltd.btg.validq.ValidQ;
import cn.zcltd.btg.validq.ValidateCallback;
import cn.zcltd.btg.validq.ValidationResult;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.HashMap;
import java.util.Map;

/**
 * 基于json规则的验证工具
 */
public class ValidJsonQ {
    private boolean returnOnFail = true; //快速返回（验证失败即返回）
    private ValidateCallback defaultValidateCallback = new DefaultValidateCallback();//验证回调
    private ValidJsonQLoader validJsonQLoader = new ValidJsonQCoreLoader();//验证器装载器
    private Map<String, Object> attr = new HashMap<>();//上下文参数

    private JSONObject config; //配置
    private String group; //分组

    private boolean initConfig = false;

    protected ValidJsonQ() {

    }

    /**
     * 获取一个验证工具
     *
     * @return 验证工具
     */
    public static ValidJsonQ create() {
        return new ValidJsonQ();
    }

    /**
     * 设置参数
     *
     * @param key   参数名称
     * @param value 参数值
     * @return this
     */
    public ValidJsonQ setAttr(String key, Object value) {
        this.attr.put(key, value);
        return this;
    }

    /**
     * 设置参数
     *
     * @param values 参数
     * @return this
     */
    public ValidJsonQ setAttr(Map<String, Object> values) {
        this.attr.putAll(values);
        return this;
    }

    /**
     * 加载json配置（从缓存）
     *
     * @param jsonConfigCache json格式配置
     * @return this
     */
    public ValidJsonQ configCache(String jsonConfigCache) {
        this.config = ValidJsonQCache.me.get(jsonConfigCache);
        this.initConfig = true;
        return this;
    }

    /**
     * 加载json配置
     *
     * @param jsonConfig json格式配置
     * @return this
     */
    public ValidJsonQ config(JSONObject jsonConfig) {
        this.config = jsonConfig;
        this.initConfig = true;
        return this;
    }

    /**
     * 加载json配置
     *
     * @param jsonConfigStr json格式配置字符串
     * @return this
     */
    public ValidJsonQ config(String jsonConfigStr) {
        return config(JSONObject.parseObject(jsonConfigStr));
    }

    /**
     * 设置验证分组
     *
     * @param group 分组
     * @return this
     */
    public ValidJsonQ group(String group) {
        this.group = group;
        return this;
    }

    /**
     * 设置失败即返回
     *
     * @return this
     */
    public ValidJsonQ failReturn() {
        this.returnOnFail = true;
        return this;
    }

    /**
     * 设置失败继续验证
     *
     * @return this
     */
    public ValidJsonQ failContinue() {
        this.returnOnFail = false;
        return this;
    }

    /**
     * 执行验证
     *
     * @param jsonObject       jsonObject类型数据
     * @param validateCallback 验证回调
     * @return 验证结果
     */
    public ValidationResult validObject(JSONObject jsonObject, ValidateCallback validateCallback) {
        try {
            if (!initConfig) {
                throw new ValidJsonQException("未初始化验证配置");
            }

            ValidQ validQ = ValidQ.create().setReturnOnFail(returnOnFail).setDefaultValidateCallback(validateCallback).setAttr(attr);

            //解释规则，装载验证器
            validJsonQLoader.loadObject(validQ, group, config, jsonObject, null, null, null);

            return validQ.valid();
        } catch (Exception e) {
            throw new ValidJsonQException(e);
        }
    }

    /**
     * 执行验证
     *
     * @param jsonObject jsonObject类型数据
     * @return 验证结果
     */
    public ValidationResult validObject(JSONObject jsonObject) {
        return validObject(jsonObject, defaultValidateCallback);
    }

    /**
     * 执行验证
     *
     * @param jsonArray        jsonArray类型数据
     * @param validateCallback 验证回调
     * @return 验证结果
     */
    public ValidationResult validList(JSONArray jsonArray, ValidateCallback validateCallback) {
        try {
            if (!initConfig) {
                throw new ValidJsonQException("未初始化验证配置");
            }

            ValidQ validQ = ValidQ.create().setReturnOnFail(returnOnFail).setDefaultValidateCallback(defaultValidateCallback).setAttr(attr);

            //解释规则，装载验证器
            validJsonQLoader.loadList(validQ, group, config, jsonArray, null, null, null);

            return validQ.valid();
        } catch (Exception e) {
            throw new ValidJsonQException(e);
        }
    }

    /**
     * 执行验证
     *
     * @param jsonArray jsonArray类型数据
     * @return 验证结果
     */
    public ValidationResult validList(JSONArray jsonArray) {
        return validList(jsonArray, defaultValidateCallback);
    }

    /**
     * 执行验证
     *
     * @param jsonArray        jsonArray类型数据
     * @param validateCallback 验证回调
     * @return 验证结果
     */
    public ValidationResult validArray(JSONArray jsonArray, ValidateCallback validateCallback) {
        try {
            if (!initConfig) {
                throw new ValidJsonQException("未初始化验证配置");
            }

            ValidQ validQ = ValidQ.create().setReturnOnFail(returnOnFail).setDefaultValidateCallback(defaultValidateCallback).setAttr(attr);

            //解释规则，装载验证器
            validJsonQLoader.loadArray(validQ, group, config, jsonArray, null, null, null);

            return validQ.valid();
        } catch (Exception e) {
            throw new ValidJsonQException(e);
        }
    }

    /**
     * 执行验证
     *
     * @param jsonArray jsonArray类型数据
     * @return 验证结果
     */
    public ValidationResult validArray(JSONArray jsonArray) {
        return validArray(jsonArray, defaultValidateCallback);
    }

    public boolean isReturnOnFail() {
        return returnOnFail;
    }

    public ValidJsonQ setReturnOnFail(boolean returnOnFail) {
        this.returnOnFail = returnOnFail;
        return this;
    }

    public ValidateCallback getDefaultValidateCallback() {
        return defaultValidateCallback;
    }

    public ValidJsonQ setDefaultValidateCallback(ValidateCallback defaultValidateCallback) {
        this.defaultValidateCallback = defaultValidateCallback;
        return this;
    }

    public ValidJsonQLoader getValidJsonQLoader() {
        return validJsonQLoader;
    }

    public ValidJsonQ setValidJsonQLoader(ValidJsonQLoader validJsonQLoader) {
        this.validJsonQLoader = validJsonQLoader;
        return this;
    }

    public Map<String, Object> getAttr() {
        return attr;
    }

    public JSONObject getConfig() {
        return config;
    }

    public ValidJsonQ setConfig(JSONObject config) {
        this.config = config;
        return this;
    }

    public String getGroup() {
        return group;
    }

    public ValidJsonQ setGroup(String group) {
        this.group = group;
        return this;
    }
}